#pragma once
#include <iostream>
#include <unordered_map>
#include <unistd.h>
#include "Log.hpp"
#include "Epoller.hpp"
#include "Connection.hpp"

class Reactor
{
    static const int gmaxevents = 64;

public:
    Reactor() : _isrunning(false) {}

    void Init(Connection *listenconn)
    {
        // 初始化epoll模型
        _epoller.Init();
        // 将listensockfd添加到epoll模型和_connections中
        _epoller.Add(listenconn->GetSockFd(), EPOLLIN | EPOLLET);
        _connections[listenconn->GetSockFd()] = listenconn;
    }

    void AddConnection(Connection *conn, uint32_t events)
    {
        if (!conn)
            return;
        _epoller.Add(conn->GetSockFd(), events);
        _connections.insert(std::make_pair(conn->GetSockFd(), conn));
    }

    bool ConnectionExists(Connection *conn)
    {
        for(auto e : _connections)
        {
            if(e.second == conn)
                return true;
        }
        return false;
    }

    void ModConnection(Connection *conn, uint32_t events)
    {
        if (!conn)
            return;

        if (!ConnectionExists(conn))
            return;
        // 修改连接对象关心的事件
        _epoller.Mod(conn->GetSockFd(), events);
        // 同步Reactor中管理连接对象容器的状态
        _connections[conn->GetSockFd()]->SetEvents(events);
    }

    void DelConnection(Connection *conn)
    {
        if (!conn)
            return;

        if (!ConnectionExists(conn))
            return;

        // 删除连接对象关心的事件
        _epoller.Del(conn->GetSockFd());   
        // 同步Reactor中管理连接对象容器的状态
        _connections.erase(conn->GetSockFd());     
    }

    void LoopOnce()
    {
        PrintBug();
        int n = _epoller.Wait(_ev, gmaxevents);
        for (int i = 0; i < n; i++)
        {
            if (_ev[i].events & EPOLLERR || _ev[i].events & EPOLLHUP)
            {
                _ev[i].events |= EPOLLIN;
                _ev[i].events |= EPOLLOUT;
            }

            if (_ev[i].events & EPOLLIN)
            {
                // 对应文件描述符的读事件就绪
                _connections[_ev->data.fd]->Read();
            }
            if (_ev[i].events & EPOLLOUT)
            {
                // 对应文件描述符的写事件就绪
                _connections[_ev->data.fd]->Write();
            }
        }
    }

    void Dispatcher()
    {
        _isrunning = true;
        while (_isrunning)
        {
            LoopOnce();
        }
        _isrunning = false;
    }

    void PrintBug()
    {
        std::cout << "fd list: ";
        for (auto e : _connections)
        {
            std::cout << e.first << " ";
        }
        std::cout << std::endl;
    }

    ~Reactor() {}

private:
    // 管理建立连接的文件描述符关心的事件，epoll模型
    Epoller _epoller;

    // 将所有的连接管理起来
    std::unordered_map<int, Connection *> _connections;

    struct epoll_event _ev[gmaxevents];

    bool _isrunning;
};